#include "PlanStorage.h"
#include <QFile>
#include <QDir>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDebug>

PlanStorage::PlanStorage()
    : m_basePath(QDir::currentPath() + "/plans/")
{
}

void PlanStorage::setBasePath(const QString& basePath)
{
    m_basePath = basePath;
    if (!m_basePath.endsWith("/")) {
        m_basePath += "/";
    }
}

QString PlanStorage::getFilePath(const QDate& date) const
{
    // 格式：plans/YYYY/MM/DD/tasks.json
    return QString("%1%2/%3/%4/tasks.json")
        .arg(m_basePath)
        .arg(date.year(), 4, 10, QChar('0'))
        .arg(date.month(), 2, 10, QChar('0'))
        .arg(date.day(), 2, 10, QChar('0'));
}

bool PlanStorage::ensureDirectoryExists(const QString& dirPath)
{
    QDir dir;
    if (!dir.exists(dirPath)) {
        return dir.mkpath(dirPath);
    }
    return true;
}

QList<PlanTask> PlanStorage::loadTasks(const QDate& date)
{
    QString filePath = getFilePath(date);
    return loadFromFile(filePath);
}

QList<PlanTask> PlanStorage::loadTasksInRange(const QDate& startDate, const QDate& endDate)
{
    QList<PlanTask> allTasks;

    QDate currentDate = startDate;
    while (currentDate <= endDate) {
        QList<PlanTask> dayTasks = loadTasks(currentDate);
        allTasks.append(dayTasks);
        currentDate = currentDate.addDays(1);
    }

    return allTasks;
}

/**
 * @brief [FDD-2025-03-021][API-003] 流式遍历任务，避免一次性加载全部到内存
 * @param startDate 开始日期
 * @param endDate 结束日期
 * @param callback 任务回调函数，返回 false 时中断遍历
 * @return 是否成功完成遍历
 */
bool PlanStorage::forEachTask(const QDate& startDate, const QDate& endDate,
                               std::function<bool(const PlanTask&)> callback)
{
    if (!callback) {
        qWarning() << "[PlanStorage][E010_INVALID_CALLBACK] Callback is null";
        return false;
    }

    if (!startDate.isValid() || !endDate.isValid() || startDate > endDate) {
        qWarning() << "[PlanStorage][E011_INVALID_RANGE] Invalid date range:"
                   << startDate << "to" << endDate;
        return false;
    }

    QDate currentDate = startDate;
    while (currentDate <= endDate) {
        // 逐日加载任务
        QString filePath = getFilePath(currentDate);
        QList<PlanTask> dayTasks = loadFromFile(filePath);

        // 逐条回调
        for (const PlanTask& task : dayTasks) {
            if (!callback(task)) {
                // 回调返回 false，中断遍历
                qDebug() << "[PlanStorage] forEachTask interrupted by callback at"
                         << currentDate;
                return false;
            }
        }

        // 立即丢弃当天任务对象，释放内存
        dayTasks.clear();
        currentDate = currentDate.addDays(1);
    }

    qDebug() << "[PlanStorage] forEachTask completed successfully from"
             << startDate << "to" << endDate;
    return true;
}

bool PlanStorage::saveTasks(const QDate& date, const QList<PlanTask>& tasks)
{
    QString filePath = getFilePath(date);
    return saveToFile(filePath, tasks);
}

bool PlanStorage::saveTask(const PlanTask& task)
{
    if (!task.isValid()) {
        qWarning() << "PlanStorage::saveTask - Invalid task";
        return false;
    }
    
    // 根据任务的开始时间确定日期
    QDate taskDate = task.getStartTime().date();
    if (!taskDate.isValid()) {
        taskDate = QDate::currentDate();
    }
    
    // 加载当天的所有任务
    QList<PlanTask> tasks = loadTasks(taskDate);
    
    // 查找是否已存在该任务
    int existingIndex = -1;
    for (int i = 0; i < tasks.size(); ++i) {
        if (tasks[i].getId() == task.getId()) {
            existingIndex = i;
            break;
        }
    }
    
    // 更新或添加任务
    if (existingIndex >= 0) {
        tasks[existingIndex] = task;
    } else {
        tasks.append(task);
    }
    
    // 保存
    return saveTasks(taskDate, tasks);
}

bool PlanStorage::deleteTask(const QString& taskId, const QDate& date)
{
    // 加载当天的所有任务
    QList<PlanTask> tasks = loadTasks(date);
    
    // 查找并删除任务
    int removeIndex = -1;
    for (int i = 0; i < tasks.size(); ++i) {
        if (tasks[i].getId() == taskId) {
            removeIndex = i;
            break;
        }
    }
    
    if (removeIndex < 0) {
        qWarning() << "PlanStorage::deleteTask - Task not found:" << taskId;
        return false;
    }
    
    tasks.removeAt(removeIndex);
    
    // 保存
    return saveTasks(date, tasks);
}

QList<PlanTask> PlanStorage::loadFromFile(const QString& filePath)
{
    QList<PlanTask> tasks;
    
    QFile file(filePath);
    if (!file.exists()) {
        return tasks;
    }
    
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "PlanStorage::loadFromFile - Cannot open file:" << filePath;
        return tasks;
    }
    
    QByteArray data = file.readAll();
    file.close();
    
    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (!doc.isObject()) {
        qWarning() << "PlanStorage::loadFromFile - Invalid JSON format";
        return tasks;
    }
    
    QJsonObject root = doc.object();
    QJsonArray tasksArray = root["tasks"].toArray();
    
    for (const QJsonValue& value : tasksArray) {
        if (value.isObject()) {
            PlanTask task = PlanTask::fromJson(value.toObject());
            if (task.isValid()) {
                tasks.append(task);
            }
        }
    }
    
    return tasks;
}

bool PlanStorage::saveToFile(const QString& filePath, const QList<PlanTask>& tasks)
{
    // 确保目录存在
    QFileInfo fileInfo(filePath);
    if (!ensureDirectoryExists(fileInfo.absolutePath())) {
        qWarning() << "PlanStorage::saveToFile - Cannot create directory:" << fileInfo.absolutePath();
        return false;
    }
    
    // 构建JSON
    QJsonArray tasksArray;
    for (const PlanTask& task : tasks) {
        tasksArray.append(task.toJson());
    }
    
    QJsonObject root;
    root["version"] = 1;
    root["tasks"] = tasksArray;
    
    // 写入文件
    QJsonDocument doc(root);
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning() << "PlanStorage::saveToFile - Cannot open file for writing:" << filePath;
        return false;
    }
    
    file.write(doc.toJson(QJsonDocument::Indented));
    file.close();
    
    return true;
}





